//**************************************************
// Description:Generate an ARP response input packet 
//**************************************************

//**************************************************
// include files
//**************************************************
`include "protocol_define.v"

module arp_gen (
    input                          clk ,
    input                          rst_n ,
    //ARP deal interface
    
    input                          ARP_gen_enable ,
    input [15:0]                   ARP_gen_hard_type, 
    input [15:0]                   ARP_gen_prot_type, 
    input [7:0]                    ARP_gen_hard_len, 
    input [7:0]                    ARP_gen_prot_len, 
    input [15:0]                   ARP_gen_op, 
    input [47:0]                   ARP_gen_src_mac, 
    input [31:0]                   ARP_gen_src_ip, 
    input [47:0]                   ARP_gen_dst_mac, 
    input [31:0]                   ARP_gen_dst_ip, 
    
    //MAC content 
    input [47:0]                   DATALINK_gen_src_mac, 
    input [47:0]                   DATALINK_gen_dst_mac,  
    
    //shake hands with next module(tx arbitration) 
    
    input                          arp_rx_rdy,
    //output  reg                        arp_ready,


    output reg[128-1:0]               arp_tx_data ,
    output reg[4-1:0]                 arp_tx_mod ,
    output reg                       arp_tx_sav ,
    output reg                      arp_tx_val ,
    output reg                       arp_tx_sop ,
    output reg                     arp_tx_eop 
    //output reg[5:0]                   //arp_tx_err 
    //output [10:0]                  arp_length ,
);

//****************************  
// signal declare
//***************************** 
    reg [15:0]                     ARP_gen_hard_type_r; 
    reg [15:0]                     ARP_gen_prot_type_r; 
    reg [7:0]                      ARP_gen_hard_len_r; 
    reg [7:0]                      ARP_gen_prot_len_r; 
    reg [15:0]                     ARP_gen_op_r; 
    reg [47:0]                     ARP_gen_src_mac_r; 
    reg [31:0]                     ARP_gen_src_ip_r; 
    reg [47:0]                     ARP_gen_dst_mac_r; 
    reg [31:0]                     ARP_gen_dst_ip_r; 
    
    //MAC content 
    reg [47:0]                     DATALINK_gen_src_mac_r; 
    reg [47:0]                     DATALINK_gen_dst_mac_r;
    
//****************************  
// FSM
//***************************** 
    localparam ARP_GEN_IDLE                    =4'd0;
    localparam ARP_GEN_RECEIVE                 =4'd1;
    localparam ARP_GEN_GENARATE                =4'd2;
    localparam ARP_GEN_SEND_0                  =4'd3;
    localparam ARP_GEN_SEND_1                  =4'd4;
    localparam ARP_GEN_SEND_2                  =4'd5;
    localparam ARP_GEN_SEND_3                  =4'd6;
    localparam ARP_GEN_END                     =4'd7;

    reg [3:0]                      arp_gen_state_c ;
    reg [3:0]                      arp_gen_state_n ;
    reg [336-1:0]                  arp_packet;
    reg                            generate_end;
//   FSM(1)
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            arp_gen_state_c <= ARP_GEN_IDLE ;
        end
        else begin
            arp_gen_state_c <= arp_gen_state_n ;
        end
    end
//   FSM(2)
    always @(*) begin
        case(arp_gen_state_c)
            ARP_GEN_IDLE:begin
                if(ARP_gen_enable == 1'b1)
                    arp_gen_state_n = ARP_GEN_RECEIVE;
                else 
                    arp_gen_state_n = ARP_GEN_IDLE;
            end

            ARP_GEN_RECEIVE:begin
                arp_gen_state_n = ARP_GEN_GENARATE;
            end

            ARP_GEN_GENARATE:begin
                if(arp_rx_rdy == 1'b1)
                arp_gen_state_n = ARP_GEN_SEND_0;
                else 
                arp_gen_state_n = ARP_GEN_GENARATE;
            end

            ARP_GEN_SEND_0:begin
                arp_gen_state_n = ARP_GEN_SEND_1; 
            end  

            ARP_GEN_SEND_1:begin
                arp_gen_state_n = ARP_GEN_SEND_2; 
            end  

            ARP_GEN_SEND_2:begin
                arp_gen_state_n = ARP_GEN_SEND_3; 
            end  

            ARP_GEN_SEND_3:begin
                arp_gen_state_n = ARP_GEN_END; 
            end  
        
            ARP_GEN_END:begin
                arp_gen_state_n = ARP_GEN_IDLE;
            end

            default:
                arp_gen_state_n = ARP_GEN_IDLE ;
            endcase
    end

// FSM(3)
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
             ARP_gen_hard_type_r    <= 16'b0; 
             ARP_gen_prot_type_r    <= 16'b0; 
             ARP_gen_hard_len_r     <= 8'b0; 
             ARP_gen_prot_len_r     <= 8'b0; 
             ARP_gen_op_r           <= 16'b0; 
             ARP_gen_src_mac_r      <= 48'b0; 
             ARP_gen_src_ip_r       <= 32'b0; 
             ARP_gen_dst_mac_r      <= 48'b0; 
             ARP_gen_dst_ip_r       <= 32'b0;
             DATALINK_gen_src_mac_r <= 48'b0; 
             DATALINK_gen_dst_mac_r <= 48'b0;

             arp_tx_data            <= 128'b0;
             arp_tx_mod             <= 4'b0;
             arp_tx_sav             <= 1'b0;
             arp_tx_val             <= 1'b0;
             arp_tx_sop             <= 1'b0;
             arp_tx_eop             <= 1'b0;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0;

             generate_end           <=1'b0;    
             arp_packet             <= 336'b0 ;
        end
        else if (arp_gen_state_c == ARP_GEN_IDLE) begin
             arp_tx_eop             <= 1'b0;
             arp_tx_mod             <= 4'b0;
             arp_tx_sav             <= 1'b0;
             arp_tx_val             <= 1'b0;
             arp_tx_sop             <= 1'b0;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0;       
        end

        else if (arp_gen_state_c == ARP_GEN_RECEIVE) begin
             ARP_gen_hard_type_r    <= ARP_gen_hard_type;  
             ARP_gen_prot_type_r    <= ARP_gen_prot_type;  
             ARP_gen_hard_len_r     <= ARP_gen_hard_len;  
             ARP_gen_prot_len_r     <= ARP_gen_prot_len;  
             ARP_gen_op_r           <= ARP_gen_op;         
             ARP_gen_src_mac_r      <= ARP_gen_src_mac;    
             ARP_gen_src_ip_r       <= ARP_gen_src_ip;     
             ARP_gen_dst_mac_r      <= ARP_gen_dst_mac;    
             ARP_gen_dst_ip_r       <= ARP_gen_dst_ip;    
             DATALINK_gen_src_mac_r <= DATALINK_gen_src_mac; 
             DATALINK_gen_dst_mac_r <= DATALINK_gen_dst_mac;    
        end
        else if (arp_gen_state_c == ARP_GEN_GENARATE) begin
             arp_packet<={
                        DATALINK_gen_dst_mac_r,
                        DATALINK_gen_src_mac_r,
                        `DATALINK_ARP,
                        ARP_gen_hard_type_r,
                        ARP_gen_prot_type_r,
                        ARP_gen_hard_len_r,
                        ARP_gen_prot_len_r,
                        ARP_gen_op_r,
                        ARP_gen_src_mac_r,
                        ARP_gen_src_ip_r,
                        ARP_gen_dst_mac_r,
                        ARP_gen_dst_ip_r 
                         };

             arp_tx_sav               <=1'b1;
             //arp_ready               <=1'b1;
        end
        else if (arp_gen_state_c == ARP_GEN_SEND_0) begin

            //arp_ready               <=1'b1;

             arp_tx_data            <= arp_packet[335:208];
             arp_tx_mod             <= 4'b0;
             arp_tx_val             <= 1'b1;
             arp_tx_sop             <= 1'b1;
             arp_tx_eop             <= 1'b0;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0/////////////////;
        end
        else if (arp_gen_state_c == ARP_GEN_SEND_1) begin
             arp_tx_data            <= arp_packet[207:80];
             arp_tx_mod             <= 4'b0;
             arp_tx_val             <= 1'b1;
             arp_tx_sop             <= 1'b0;
             arp_tx_eop             <= 1'b0;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0/////////////////;
        end
        else if (arp_gen_state_c == ARP_GEN_SEND_2) begin
             arp_tx_data            <= {arp_packet[79:0],48'b0};
             arp_tx_mod             <= 4'b0;
             arp_tx_val             <= 1'b1;
             arp_tx_sop             <= 1'b0;
             arp_tx_eop             <= 1'b0;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0/////////////////;
        end
        else if (arp_gen_state_c == ARP_GEN_SEND_3) begin
             arp_tx_data            <= 48'h12_34_56_00_00_00;
             arp_tx_mod             <= 4'hc;////////
             arp_tx_val             <= 1'b1;
             arp_tx_sop             <= 1'b0;
             arp_tx_eop             <= 1'b1;
             //arp_tx_err             <= 6'b0;
             //arp_length             <= 11'b0/////////////////;
        end
        else if (arp_gen_state_c == ARP_GEN_END) begin
             
            
              arp_tx_val             <= 1'b0;
             arp_tx_sav             <= 1'b0;
             arp_tx_eop             <= 1'b0;
    end
    else begin
             arp_tx_data            <= arp_tx_data;
             arp_tx_mod             <= arp_tx_mod;
             arp_tx_sav             <= arp_tx_sav;
             arp_tx_val             <= arp_tx_val;
             arp_tx_sop             <= arp_tx_sop;
             arp_tx_eop             <= arp_tx_eop;
             //arp_tx_err             <= //arp_tx_err;
             //arp_length             <= //arp_length;
    end
end
endmodule